package com.pine.app.module.security.oauth.support;


import com.pine.app.module.security.core.common.enums.ErrorType;
import com.pine.app.module.security.oauth.exception.AuthenticationException;
import com.pine.app.module.security.oauth.exception.ClientInfoNotFoundException;
import com.pine.app.module.security.oauth.provider.DefaultOAuth2ClientRequest;
import com.pine.app.module.security.oauth.provider.OAuth2Authentication;
import com.pine.app.module.security.oauth.provider.OAuth2ClientRequest;
import com.pine.app.module.security.oauth.provider.client.ClientDetails;
import com.pine.app.module.security.oauth.provider.client.ClientDetailsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.Set;


/**
 * @author XYJXUST
 * @date 2018-4-4
 **/
public abstract class AbstractPreparableIntegrationValidator implements OAuthRequestValidator {


    protected ClientDetailsService clientDetailsService;


    @Autowired
    public void setClientDetailsService(ClientDetailsService clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    public AbstractPreparableIntegrationValidator() {

    }

    public AbstractPreparableIntegrationValidator(ClientDetailsService clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    protected abstract OAuth2Authentication checkParam(HttpTokenRequest request);


    @Override
    public OAuth2Authentication validateParams(HttpTokenRequest request) {
        OAuth2Authentication oAuth2Authentication = checkParam(request);
        oAuth2Authentication.setEnableRefresh(request.enableRefresh());
        //校验请求传入参数
        return oAuth2Authentication;
    }

    /**
     * @Description: 校验客户端信息
     * @Author: xiaoyuan
     * @Date: 2020/3/6 17:01
     */
    protected ClientDetails checkClientInfo(HttpTokenRequest request) {
        checkClientId(request);
        checkClientSecret(request);
        //获取客户端信息
        ClientDetails clientDetails = clientDetailsService.loadClientDetail(request.getClientCredentials().getPrincipal());
        if (clientDetails == null || clientDetails.isExpiredTime()) {
            ErrorType.ILLEGAL_CLIENT_ID.throwThis(ClientInfoNotFoundException::new);
        }
        if (!clientDetails.getAuthorizedGrantTypes().contains(request.getGrantType())) {
            ErrorType.UNSUPPORTED_GRANT_TYPE.throwThis(ClientInfoNotFoundException::new);
        }
        if (!clientDetails.getClientId().equals(request.getClientCredentials().getPrincipal())) {
            ErrorType.ILLEGAL_CLIENT_ID.throwThis(ClientInfoNotFoundException::new);
        }
        if (!clientDetails.getClientSecret().equals(request.getClientCredentials().getCredentials())) {
            ErrorType.ILLEGAL_CLIENT_SECRET.throwThis(ClientInfoNotFoundException::new);
        }
        return clientDetails;
    }

    protected OAuth2ClientRequest coverOauth2Request(ClientDetails clientDetails, HttpTokenRequest request) {

        return new DefaultOAuth2ClientRequest(clientDetails.getClientId(), clientDetails.getClientSecret()
                , clientDetails.getClientName(), clientDetails.getScope(),
                clientDetails.getResources(), clientDetails.getRoles(), request.getGrantType(),
                clientDetails.getAccessTokenValiditySeconds()
                , clientDetails.getRefreshTokenValiditySeconds());

    }

    protected void checkClientId(HttpTokenRequest request) {
        if (request.getClientCredentials() == null || StringUtils.isBlank(request.getClientCredentials().getPrincipal())) {
            ErrorType.CLIENT_NOT_NULL.throwThis(AuthenticationException::new);
        }
    }

    protected void checkClientSecret(HttpTokenRequest request) {
        if (request.getClientCredentials() == null || StringUtils.isBlank(request.getClientCredentials().getCredentials())) {
            ErrorType.CLIENT_SECRET_NOT_NULL.throwThis(AuthenticationException::new);
        }
    }

    protected void checkRedirectUri(String redirectUri) {
        if (StringUtils.isBlank(redirectUri)) {
            throw new AuthenticationException(ErrorType.REDIRECT_URI_NOT_NULL);
        }
        if (!redirectUri.matches("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")) {
            throw new AuthenticationException(ErrorType.REDIRECT_URI_NOT_NULL, "redirect_uri错误，非uri连接");
        }

    }

    protected void checkScope(Set<String> requestScope,Set<String> supportScope) {
        if(CollectionUtils.isEmpty(requestScope)){
            ErrorType.SCOPE_NOT_NULL.throwThis(AuthenticationException::new);
        }
        if (!CollectionUtils.isEmpty(requestScope) && !CollectionUtils.isEmpty(supportScope)) {
            requestScope.forEach(scote -> {
                if (!supportScope.contains(scote)) {
                    ErrorType.SCOPE_OUT_OF_RANGE.throwThis(AuthenticationException::new);
                }
            });
        }
    }
}
